package taskTracker.ui.lwuit;

import java.util.Enumeration;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import taskTracker.Interval;
import taskTracker.Project;
import taskTracker.Task;
import taskTracker.TimeEntries;

import com.sun.lwuit.ComboBox;
import com.sun.lwuit.Command;
import com.sun.lwuit.Form;
import com.sun.lwuit.Label;
import com.sun.lwuit.TextArea;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.events.SelectionListener;
import com.sun.lwuit.layouts.BoxLayout;
import com.sun.lwuit.list.DefaultListModel;
import com.sun.lwuit.list.ListModel;

/**
 * A dialog that lets the user chooses a Project and a Task to log time to.
 * It also allows him to enter an optional comment.
 * He can also choose a time after which an alert is shown to him.
 * @author aseldawy
 *
 */
public class LogTimeForm extends Form implements SelectionListener, ActionListener {

	/**59 seconds. We don't make an exact minute to avoid missing a second*/
	private static final long ABOUT_MINUTE = 59 * 1000;

	/**Command for accepting input*/
	final Command cmdOk = new Command("Ok");

	/**Command for cancellation*/
	final Command cmdCancel = new Command("Cancel");
	
	/**A combo box for choosing a list*/
	private final ComboBox cmbProject = new ComboBox();
	
	/**A combo box for choosing a task*/
	private final ComboBox cmbTask = new ComboBox();
	
	/**A note associated with logged time entry*/
	private final TextArea txtComment = new TextArea();
	
	/**Time to wait till the next alert*/
	private final ComboBox cmbAlertAfter = new ComboBox();
	
	/**A timer for logging time and displaying alerts*/
	private final Timer timer = new Timer();
	
	/**The task that logs time in background*/
	private TimerTask logTimeTask;
	
	/**The task that shows a status alert to the user*/
	private TimerTask statusAlertTask;
	
	/**The task in which we currently log time*/
	private Task currentTask;
	
	/**The time that should be used to as a starting time for logging.*/
	private long startLogTime;

	/**The dialog that shows the current status to the user*/
	private StatusAlert statusAlertDialog;
	
	public LogTimeForm() {
		super("Log time");
		super.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
		
		Label label;
		super.addComponent(label = new Label("Project"));
		super.addComponent(cmbProject);
		cmbProject.setLabelForComponent(label);
		
		super.addComponent(label = new Label("Task"));
		super.addComponent(cmbTask);
		cmbTask.setLabelForComponent(label);
		
		super.addComponent(label = new Label("Comment"));
		super.addComponent(txtComment);
		txtComment.setLabelForComponent(label);
		
		cmbAlertAfter.addItem(new Interval(10*1000));
		cmbAlertAfter.addItem(Interval.minutes(2));
		cmbAlertAfter.addItem(Interval.minutes(5));
		cmbAlertAfter.addItem(Interval.minutes(10));
		cmbAlertAfter.addItem(Interval.minutes(15));
		cmbAlertAfter.addItem(Interval.minutes(30));
		cmbAlertAfter.addItem(Interval.hours(1));
		cmbAlertAfter.addItem(Interval.hours(2));
		super.addComponent(label = new Label("Alert me after"));
		super.addComponent(cmbAlertAfter);
		cmbAlertAfter.setLabelForComponent(label);
		
		super.addCommand(cmdOk);
		super.addCommand(cmdCancel);
		super.addCommandListener(this);
		
		cmbProject.addSelectionListener(this);
	}
	
	/**
	 * Sets all task lists in system
	 * @param projectsModel
	 */
	public void setProjects(ListModel projectsModel) {
		cmbProject.setModel(projectsModel);
		cmbProject.addSelectionListener(this);
	}

	public void setProjects(Vector projects) {
		// Remove all times
		while (cmbProject.size() > 0)
			cmbProject.getModel().removeItem(0);
		// Add only given projects
		for (Enumeration e = projects.elements();e.hasMoreElements();) {
			cmbProject.getModel().addItem(e.nextElement());
		}
		cmbProject.addSelectionListener(this);
	}
	
	public void selectionChanged(int from, int to) {
		if (cmbProject.size() > to) {
			Project selectedProject = (Project) cmbProject.getModel().getItemAt(to);
			((DefaultListModel)cmbTask.getModel()).removeAll();
			for (Enumeration e = selectedProject.getTasks().elements(); e.hasMoreElements();) {
				cmbTask.getModel().addItem(e.nextElement());
			}
		}
	}
	
	/**
	 * Set timer tasks to start logging time in currently selected task
	 */
	private void startLogging() {
		currentTask = (Task) cmbTask.getSelectedItem();
		// Set current time as the time to start logging
		startLogTime = System.currentTimeMillis();
		
		if (logTimeTask != null)
			throw new IllegalStateException("Cannot start logging time while the application is currently logging time");

		logTimeTask  = new TimerTask() {
			public void run() {
				TimeEntries.getInstance().logTime(currentTask, startLogTime, logTimeTask.scheduledExecutionTime(), txtComment.getText());
				startLogTime = logTimeTask.scheduledExecutionTime();
			}
		};
		// Start the task
		timer.schedule(logTimeTask, ABOUT_MINUTE, ABOUT_MINUTE);
	}
	
	/**
	 * Stops logging time any more in the program.
	 */
	private void stopLogging() {
		if (logTimeTask == null)
			throw new IllegalStateException("Cannot stop logging time while the application is not logging time");
		logTimeTask.cancel();
		logTimeTask = null;
	}

	/**
	 * Create a dialog that shows current status.
	 * @return
	 */
	private StatusAlert getStatusAlertDialog() {
		if (this.statusAlertDialog == null) {
			this.statusAlertDialog = new StatusAlert();
			this.statusAlertDialog.addCommandListener(this);
		}
		return this.statusAlertDialog;
	}

	public void show() {
		// If already logging time ...
		if (logTimeTask != null) {
			// ... redirect him to status alert
			// show it by firing the timer task
			statusAlertTask.run();
		} else {
			super.show();
		}
	}

	public void prepare(Vector projects) {
		setProjects(projects);
	}

	public String getComment() {
		return txtComment.getText();
	}

	public Task getTask() {
		return (Task) cmbTask.getSelectedItem();
	}

	public long getInterval() {
		return ((Interval)cmbAlertAfter.getSelectedItem()).period;
	}

	public void actionPerformed(ActionEvent evt) {
		// TODO Auto-generated method stub
		
	}
	
}
